#!/usr/bin/env python

from kivy.metrics import dp
from kivy.logger import Logger
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.button import Button
from kivy.uix.floatlayout import FloatLayout
from kivy.uix.gridlayout import GridLayout
from kivy.uix.label import Label
from kivy.uix.popup import Popup
from kivy.uix.scrollview import ScrollView
from kivy.uix.spinner import Spinner
from kivy.uix.textinput import TextInput

from amgineirc.view.messageView import MessageView
from amgineirc.viewModel.settings.trustedViewModel import TrustedViewModel

__all__ = ['EditTrustedPopup', 'TrustedView']

class EditTrustedPopup(Popup, MessageView):
    
    def __init__(self,
                 command,
                 nick, real_name,
                 server, server_name_list,
                 rule_name, rule_name_list,
                 validate_handler):
        # clean the nick
        if len(nick) > 0 and nick[0] == '@':
            nick = nick[1:]
        self.key = nick.strip() + ':' + server.strip()
        self.command = command
        self.validate_handler = validate_handler
        layout = FloatLayout()
        Popup.__init__(self,
                       title=command + ' ' + nick,
                       content=layout,
                       size_hint=(None, None),
                       size=(400, 500),
                       auto_dismiss=False)
        MessageView.__init__(self)
        # nick
        self._nick = nick
        label = self.buildFormLabel('Nick',
                                    '',
                                    size_hint=(0.5, 0.2),
                                    pos_hint={'x':0.0, 'y':0.8})
        layout.add_widget(label)
        if command == TrustedView.create_command:
            # let the user enter an nick
            self.nick_input = TextInput(text=nick,
                                        multiline=False,
                                        size_hint=(0.5, 0.2),
                                        pos_hint={'x':0.5, 'y':0.8})
            layout.add_widget(self.nick_input)
        else:
            # the nick is not editable
            label = Label(text=nick,
                          size_hint=(0.5, 0.2),
                          pos_hint={'x':0.5, 'y':0.8})
            layout.add_widget(label)
        # real name
        label = self.buildFormLabel('Real Name',
                                    '',
                                    size_hint=(0.5, 0.2),
                                    pos_hint={'x':0.0, 'y':0.6})
        self.real_name_input = TextInput(text=real_name,
                                    multiline=False,
                                    size_hint=(0.5, 0.2),
                                    pos_hint={'x':0.5, 'y':0.6})
        layout.add_widget(label)
        layout.add_widget(self.real_name_input)
        # server
        self._server = server
        label = self.buildFormLabel('Server',
                                    '',
                                    size_hint=(0.5, 0.2),
                                    pos_hint={'x':0.0, 'y':0.4})
        layout.add_widget(label)
        if command == TrustedView.create_command:
            # let the user enter a server domain
            self.server_input = Spinner(text=rule_name,
                                        values=server_name_list,
                                        size_hint=(0.5, 0.2),
                                        pos_hint={'x':0.5, 'y':0.4})
            layout.add_widget(self.server_input)
        else:
            # the server is not editable
            label = Label(text=server,
                          size_hint=(0.5, 0.2),
                          pos_hint={'x':0.5, 'y':0.4})
            layout.add_widget(label)
        # rule_name
        rule_name_list.insert(0, '')
        label = self.buildFormLabel('Rotary Encryption Rule',
                                    'This is the rotary encryption rule specifically created for you and this nick.',
                                    size_hint=(0.5, 0.2),
                                    pos_hint={'x':0.0, 'y':0.2})
        self.rule_name_input = Spinner(text=rule_name,
                                        values=rule_name_list,
                                        size_hint=(0.5, 0.2),
                                        pos_hint={'x':0.5, 'y':0.2})
        layout.add_widget(label)
        layout.add_widget(self.rule_name_input)
        # command button
        layout.add_widget(Button(text=TrustedView.submit_command,
                                 size_hint=(0.5, 0.1),
                                 pos_hint={'x':0.0, 'y':0.0},
                                 on_press=self.validate_data))
        layout.add_widget(Button(text='Cancel',
                                 size_hint=(0.5, 0.1),
                                 pos_hint={'x':0.5, 'y':0.0},
                                 on_press=self.dismiss))
          

    def validate_data(self, instance):
        if self.command == TrustedView.create_command:
            ok, msg = self.validate_handler(instance.text,
                                            self.key,
                                            self.nick_input.text.strip(),
                                            self.real_name_input.text.strip(),
                                            self.server_input.text.strip(),
                                            self.rule_name_input.text)
        else:
            ok, msg = self.validate_handler(instance.text,
                                            self.key,
                                            self._nick,
                                            self.real_name_input.text.strip(),
                                            self._server,
                                            self.rule_name_input.text)
        if ok:
            self.dismiss()
        else:
            self.message_warn(msg)
                

class _TrustedRecordButton(Button, MessageView):
    def __init__(self, nick, real_name, server, rule_name, vm_command_option_handler, **kargs):
        if 'text' in kargs:
            del(kargs['text'])
        kargs['markup'] = True
        kargs['on_press'] = self.w_handle_trusted_record_button_on_press
        kargs['size_hint'] = (1.0, None)
        kargs['height'] = dp(50)
        Button.__init__(self, **kargs)
        MessageView.__init__(self)
        self.reset_text(nick, real_name, server, rule_name)
        self.vm_command_option_handler = vm_command_option_handler
        
    def reset_text(self, nick, real_name, server, rule_name):
        self.nick = nick
        self.server = server
        self.text = "[b]%s[/b] %s %s [b]%s[/b]" % (nick, real_name, server, rule_name)
        
    def w_handle_trusted_record_button_on_press(self, instance):
        self.select_options('Options for ' + self.nick,
                            TrustedView.commands,
                            self.vm_command_option_handler,
                            self.nick, self.server)
            

class _TrustedListView(ScrollView):
    def __init__(self, command_option_handler, **kargs):
        kargs['do_scroll_x'] = False
        ScrollView.__init__(self, **kargs)
        # view model command handling method
        self.command_option_handler = command_option_handler
        # create a default grid layout with custom width/height
        self._layout = GridLayout(cols=1,
                                  size_hint=(1.0, None))
        # when we add children to the grid layout, its size doesn't change at
        # all. we need to ensure that the height will be the minimum required to
        # contain all the childs. (otherwise, we'll child outside the bounding
        # box of the childs)
        self._layout.bind(minimum_height=self._layout.setter('height'))
        self.add_widget(self._layout)
        
    def log(self, nick, real_name, server, rule_name):
        w = _TrustedRecordButton(nick, real_name, server, rule_name,
                                self.command_option_handler)
        y = self.scroll_y
        self._layout.add_widget(w)
        # if the scroll view was scrolled to the end
        # then stay at the end
        if y == 1.0:
            self.scroll_y = y
        return w


class TrustedView(FloatLayout, MessageView):
    """a view for the trusteds page
        
        use bind_apply to bind the vm method to read and store the vars
        use bind_reset to bind the vm method to reset the vars

    """
    submit_command = 'Submit'
    create_command = 'Add A New Trusted Nick'
    delete_command = 'Delete'
    edit_command = 'Edit'
    
    commands = [edit_command, delete_command]

    page_intro = "This page is where you can create, edit and delete your IRC trusted nick records."\
                 " You can edit or delete a trusted nick record by touching it in the list."

    def __init__(self, appdata, **kargs):
        FloatLayout.__init__(self, **kargs)
        MessageView.__init__(self)
        self._appdata = appdata
        # page heading
        self.intro = Label(text=self.__class__.page_intro,
                           markup = True,
                           size_hint=(1.0, 0.4),
                           pos_hint={'x':0.0, 'y':0.6},
                           line_height=1.5)
        self.bind(width=self.on_width_handler)
        self.add_widget(self.intro)
        # list of current trusteds
        self.add_button = Button(text=self.__class__.create_command,
                                 size_hint=(1.0, 0.2),
                                 pos_hint={'x':0.0, 'y':0.4})
        self.add_button.bind(on_press=self.w_add_button_handler)
        self.list_view = _TrustedListView(self.w_command_option_handler,
                                          size_hint=(1.0, 0.4),
                                          pos_hint={'x':0.0, 'y':0.0})
        self.add_widget(self.add_button)
        self.add_widget(self.list_view)
        self._trusteds = {}
        self.vm_option_command_handler = lambda **kargs : None
        # initialize the view model
        TrustedViewModel(self, appdata)

    def on_width_handler(self, instance, value):
        if value > 40:
            value -= 20
        self.intro.text_size = (value-20, None)
 
    # widget methods
            
    def w_command_option_handler(self, command, target, server):
        # the user has selected a command for a trusted record
        # instance is a _TrustedOptionButton
        if self.vm_option_command_handler is not None:
            self.vm_option_command_handler(command, target, server)
            
    def w_add_button_handler(self, instance):
        if self.vm_option_command_handler is not None:
            self.vm_option_command_handler(instance.text, '', '')
        
    # vm methods

    def vm_add_trusted(self, nick, real_name, server, rule_name):
        key = nick.strip() + ':' + server.strip()
        if key not in self._trusteds:
            self._trusteds[key] = self.list_view.log(nick, real_name, server, rule_name)

    def vm_show_trusted_added(self, nick, real_name, server, rule_name):
        self.vm_add_trusted(nick, real_name, server, rule_name)
        # inform user of the added trusted
        self.message_success('Added "%s"' % (nick))
        
    def vm_show_trusted_edited(self, nick, real_name, server, rule_name):
        key = nick.strip() + ':' + server.strip()
        if key in self._trusteds:
            self._trusteds[key].reset_text(nick, real_name, server, rule_name)
            # inform user of the edit
            self.message_success('Modified "%s"' % (nick))

    def vm_show_trusted_deleted(self, nick, server):
        key = nick.strip() + ':' + server.strip()
        if key in self._trusteds:
            text = self._trusteds[key].text
            self._trusteds[key].parent.remove_widget(self._trusteds[key])
            del(self._trusteds[key])
            # inform user of the deleted trusted
            self.message_success('Deleted "%s"' % (nick))
        
    def vm_bind_command(self, func):
        # func must accept **kargs
        # 'command', 'nick'
        self.vm_option_command_handler = func
